package io.github.junxworks.qt.config.ds;

import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingValue;

import com.google.common.collect.Range;
import com.google.common.collect.Sets;

import io.github.junxworks.junx.core.util.DateUtils;
import io.github.junxworks.junx.core.util.StringUtils;

public class TsCodeTradeDateShardingAlgorithm implements ComplexKeysShardingAlgorithm<String> {

	private static final Date START = DateUtils.parseDate("2015-01-01");

	private static final Date END = DateUtils.parseDate("2030-01-01");

	private static final int count = 5;

	private static final String COLUMN_TSCODE = "key_value";

	private static final String COLUMN_TRADEDATE = "trade_date";

	@Override
	public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<String> shardingValue) {
		final Set<String> suffix = Sets.newHashSet();
		Map<String, Collection<String>> nasValues = shardingValue.getColumnNameAndShardingValuesMap();
		//固定值条件
		Set<String> codes = Sets.newHashSet();
		Set<String> dates = Sets.newHashSet();
		if (nasValues != null && !nasValues.isEmpty()) {
			Collection<String> tsCodes = nasValues.get(COLUMN_TSCODE);
			if (tsCodes != null && !tsCodes.isEmpty()) {
				//有tsCode条件
				tsCodes.forEach(c -> {
					codes.add(getTsCodeTag(c));
				});
			}
			Collection<String> tradeDates = nasValues.get(COLUMN_TRADEDATE);
			if (tradeDates != null && !tradeDates.isEmpty()) {
				tradeDates.forEach(d -> {
					dates.add(getDateSuffix(d));
				});
			}
		}
		//范围条件
		Map<String, Range<String>> rangeValues = shardingValue.getColumnNameAndRangeValuesMap();
		if (rangeValues != null && !rangeValues.isEmpty()) {
			Range<String> tradeDates = rangeValues.get(COLUMN_TRADEDATE);
			if (tradeDates != null && !tradeDates.isEmpty()) {
				String le = null;
				String ue = null;
				if (tradeDates.hasLowerBound()) {
					le = tradeDates.lowerEndpoint();
				}
				if (tradeDates.hasUpperBound()) {
					ue = tradeDates.upperEndpoint();
				}
				if (StringUtils.notNull(le) && StringUtils.isNull(ue)) {
					Date d = DateUtils.parse(le, "yyyyMMdd");
					while (d.getTime() <= END.getTime()) {
						dates.add(getDateSuffix(d));
						d = DateUtils.addMonths(d, 1);
					}
				}
				if (StringUtils.notNull(le) && StringUtils.notNull(ue)) {
					Date d = DateUtils.parse(le, "yyyyMMdd");
					Date ud = DateUtils.parse(ue, "yyyyMMdd");
					while (d.getTime() <= ud.getTime()) {
						dates.add(getDateSuffix(d));
						d = DateUtils.addMonths(d, 1);
					}
				}
				if (StringUtils.isNull(le) && StringUtils.notNull(ue)) {
					Date d = DateUtils.parse(ue, "yyyyMMdd");
					while (d.getTime() >= START.getTime()) {
						dates.add(getDateSuffix(d));
						d = DateUtils.addMonths(d, -1);
					}
				}
			}
		}

		if (!codes.isEmpty() && !dates.isEmpty()) {
			//都不为空
			codes.forEach(c -> {
				dates.forEach(d -> {
					suffix.add("_" + c + "_" + d);
				});
			});
		} else if (!codes.isEmpty() && dates.isEmpty()) {
			//code不为空
			codes.forEach(c -> {
				suffix.add("_" + c + "_");
			});
		} else if (codes.isEmpty() && !dates.isEmpty()) {
			//date不为空
			dates.forEach(d -> {
				suffix.add("_" + d);
			});
		}
		if (!suffix.isEmpty()) {
			return availableTargetNames.stream().filter(t -> {
				for (String s : suffix) {
					if (t.contains(s)) {
						return true;
					}
				}
				return false;
			}).collect(Collectors.toList());
		}
		return availableTargetNames;
	}

	private String getTsCodeTag(String tsCode) {
		int code = tsCode.hashCode();
		return String.valueOf((code < 0 ? (code * -1) : code) % count);
	}

	private String getDateSuffix(String date) {
		return date.substring(0, 6);
	}

	private String getDateSuffix(Date date) {
		return DateUtils.format(date, "yyyyMM");
	}

	@Override
	public void init(Properties props) {
	}

}
